package com.pray.client;

import com.pray.protocol.RpcRequest;
import com.pray.protocol.RpcResponse;
import com.pray.rpc.RpcRequestBody;
import com.pray.rpc.RpcResponseBody;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * RpclientProxy RPC服务端代理对象
 *
 *
 * @author 春江花朝秋月夜
 * @since 2024/1/8 20:22
 */
public class RpClientProxy implements InvocationHandler {
    @SuppressWarnings("unchecked")
    public <T> T getService(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(
                clazz.getClassLoader(),
                new Class<?>[]{clazz},
                this
        );
    }

    //实现代理接口
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //1：信息编码
        RpcRequestBody rpcRequestBody = RpcRequestBody.builder()
                .interfaceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .paramTypes(method.getParameterTypes())
                .parameters(args)
                .build();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(rpcRequestBody);
        byte[] bytes = baos.toByteArray();

        //2:创建RPC协议
        RpcRequest rpcRequest=RpcRequest.builder()
                .header("rpc-framework")
                .body(bytes)
                .build();
        //3:发送信息
        RpcResponse rpcResponse=new RpcClientTransfer().sendRpcRequest(rpcRequest);

        //4:解析部分，获取响应
        String header=rpcResponse.getHeader();
        byte[] body=rpcResponse.getBody();
        if (header.equals("rpc-framework")){
            ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(body);
            ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
            RpcResponseBody rpcResponseBody= (RpcResponseBody) objectInputStream.readObject();
            return rpcResponseBody.getReturnObject();
        }
        return null;
    }
}
